1. try-with-resource
  2. 강한 결합과 느슨한 결합
  3. 직렬화와 역직렬화
  4. 자바의 동시성 이슈(공유자원 접근)
  5. Mutable 객체와 Immutable 객체의 차이점
  6. 자바에서 null을 안전하게 다루는 방법
  7. JDK와 JRE의 차이점

1. try-with-resource

  • java에서 자동으로 자원을 관리해주는 구조
  • 자원을 사용하는 코드를 작성할 때 close()처리를 하지 않아도 자동으로 자원 해제
  • 리소스 누수를 방지하고 코드의 가독성과 안전성을 높임

Question

try-with-resources가 무엇인가요?

try-with-resources는 자원을 자동으로 관리해주는 구조입니다. AutoCloseable 인터페이스를 구현한 객체를 사용하는 경우 close() 메서드를 호출하지 않아도 try 블럭이 해제될 때 자동으로 자원을 해제해 주어 리소스 누수를 방지하고 코드의 가독성과 안전성을 높일 수 있습니다.

파일 입출력 관련된 클래스, 데이터베이스 관련 클래스, 네트워크 관련 클래스 등등

Question

기존 try-finally 방식과 try-with-resources 방식의 차이는 무엇인가요?

try-finally 방식에서는 자원을 명시적으로 닫기 위해 finally 블록에서 close() 메서드를 호출해야 합니다. 하지만, 예외가 발생하거나 코드가 중단될 경우 자원을 제대로 닫지 못할 위험이 있습니다.
반면, try-with-resources는 자원이 자동으로 닫히도록 보장합니다. 자원을 관리하는 코드가 간소화되고 예외 처리 중에도 리소스 누수가 발생하지 않습니다.

2. 강한 결합과 느슨한 결합

강한 결합

  • 클래스나 모듈간의 의존성이 높은 상태
  • 클래스 간의 변경이 어렵고, 하나의 클래스가 변경되면 다른 클래스도 함께 수정해야 하는 경우가 많음
  • 의존성이 높다 (다른 클래스에 의존함)
  • 재사용성이 낮다 (다른 클래스와 연결되어 있어 독립적 사용이 어려움)
  • 테스트가 어렵다 (다른클래스 없이 테스트 수행 어려움)

느슨한 결합

  • 클래스나 모듈간의 의존성이 낮은 상태
  • 클래스간 상호작용은 인터페이스나 추상클래스등을 통해 이루어짐
  • 의존성이 낮고, 재사용성이 높고, 테스트가 용이하고, 확장성이 우수함

느슨한 결합을 구현하는 방법

  • 인터페이스나 추상클래스에 의존하도록 설계
  • 객체 간 의존성을 생성자, 메서드, 필드주입방식으로 외부에서 주입(DI)

Question

강한 결합과 느슨한 결합의 차이를 설명하세요.

강한 결합은 클래스 간 의존성이 높아 코드 변경과 재사용이 어렵습니다. 반면, 느슨한 결합은 인터페이스, DI, 또는 팩토리 패턴 등을 통해 의존성을 줄이고, 확장성과 유지보수성을 높이는 설계 방식입니다.

Question

의존성 주입(DI)이 느슨한 결합에 기여하는 이유를 설명하세요.

DI는 객체 생성과 관리를 외부에서 처리하여 클래스 간 결합도를 낮추는 대표적인 방법입니다.

3. 직렬화와 역직렬화

직렬화(Serialization)

  • 객체를 바이트 스트림으로 변환하는 과정
  • 객체의 상태를 저장하거나 다른 환경으로 전송하기 위해 사용
  • 네트워크 통신시 객체를 전송 가능하도록 변환

역직렬화(Deserialization)

  • 직렬화된 바이트 스트림을 다시 객체로 복원하는 과정
  • 저장된 객체 데이터를 다시 사용할 수 있도록 복원
  • 네트워크로 받은 데이터를 객체 형태로 변환

Question

직렬화와 역직렬화란 무엇인가요?

직렬화는 객체를 바이트 스트림으로 변환하여 객체 상태를 저장하거나 네트워크 통신에 사용하는 방법이고 역직렬화는 반대로 바이트 스트림으로 변환된 객체를 다시 객체르 변환하는 과정입니다.

Question

직렬화의 장/단점

저장하거나 네트워크 전송시에 간편하고 복잡한 데이터 전송이 가능하다는 장점이 있지만 직렬화하거나 역직렬화 하는 과정에서 cpu 사용량이 증가해 성능이 저하할 수 있습니다.

Question

직렬화를 위해 필요한 조건은 무엇인가요?

클래스가 Serializable 인터페이스를 구현해야 하며, 객체가 참조하는 모든 객체도 직렬화 가능해야 합니다.

4. 자바의 동시성 이슈(공유자원 접근)

동시성이란?

  • 여러 스레드가 동시에 실행되는 환경
  • 자원을 효율적으로 활용하기 위해 구현
  • 멀티스레딩을 통해 이루어지며, 여러 작업이 교차하면서 실행될 수 있음

공유자원과 동시성 이슈

  • 여러 스레드가 동시에 접근하는 자원
  • 여러 스레드가 동시에 자원을 읽거나 수정하려 할 때 일관성 문제나 예상치 못한 문제가 발생할 수 있음

주요 동시성 이슈

  • 경쟁 상태(RaceCondition) : 여러 스레드가 동시에 공유 자원에 접근하여 동시에 값을 변경하여 덮어씌우는 경우
  • 교착 상태(DeadLock) : 여러 스레드가 서로의 자원을 기다리며 무한 대기상태
  • 기아 상태(Starvation) : 우선순위가 낮은 스레드가 cpu 시간을 배정받지 못해 무한 지연되는 현상

Question

자바의 동시성 이슈에 대해 설명해주세요

여러 스레드가 동시에 실행되는 상황을 의미합니다. 동시성 문제는 여러 스레드가 공유 자원에 동시에 접근하려 할 때 발생할 수 있습니다. 동시성 이슈는 프로그램의 정확성과 성능에 큰 영향을 줄 수 있습니다.

Question

Deadlock은 무엇이며, 이를 방지하는 방법은 무엇인가요?

데드락은 여러 스레드가 동시에 자원에 접근하였을 때 자원을 기다리며 무한 대기에 빠지는 현상입니다. 방지하는 방법은 접근 순서를 고정하거나, 타임아웃을 설정하거나, lock을 사용하는 방법이 있습니다.

Question

동기화와 lock의 차이는?

동기화는 JVM이 제공하는 기본 동기화 메커니즘이며, Lock은 JAVA API에서 제공하는 기능으로 더 세밀한 제어가 가능합니다.

5. 자바의 Mutable 객체와 Immutable 객체의 차이점

Mutable 객체

  • 상태를 변경할 수 있는 객체
  • 객체 생성 후 필드값을 변경 가능
  • 메모리 효율적, 동시성 문제 발생 가능성 있음
  • StringBuilder, ArrayList, HashMap 등

Immutable 객체

  • 상태가 변하지 않는 객체
  • 상태 변경시 새 객체를 생성해야 하므로 메모리와 CPU 사용량 증가
  • 안전한 스레드 작업 가능(동시성 문제 없음), 메모리 사용량 증가
  • String, Integer, LocalDate

Question

Mutable 객체와 Immutable 객체의 차이를 설명해주세요

Mutable객체는 상태가 변할 수 있는 객체로 대표적으로 StringBuilder, List, HashMap 등이 있습니다. Immutable 객체는 상태가 변하지 않는 객체로 String, Integer 등이 있습니다. Mutable 객체는 주로 상태가 많이 변하는 객체에 사용되어 메모리엔 효율적이지만 동시성 문제가 발생할 수 있습니다. Immutable 객체는 주로 상태가 많이 변하지 않는 객체에 사용되며 동시성 이슈가 발생하지 않아 안전하지만 메모리 사용량이 증가할 수 있습니다.

Question

Immutable 객체를 만들기 위해 어떤 Java 키워드를 사용할 수 있나요?

final 을 사용하여 불변성을 보장하거나, private으로 선언하여 외부에서 변경할 수 없게 합니다.

Question

Immutable 객체는 메모리와 성능 측면에서 어떤 단점이 있으며, 이를 극복할 방법은 무엇인가요?

항상 새로운 객체를 생성해 불필요한 객체 생성과 메모리 사용이 증가할 수 있어 성능 저하가 발생할 수 있습니다. 이를 극복하기 위해선 객체를 재사용하거나 캐싱이나 Builder 패턴을 사용하는 전략을 사용할 수 있습니다.

6. 자바에서 null을 안전하게 다루는 방법

Optional

  • Optional 클래스는 null 값을 감싸는 방법을 제공합니다.
  • Optional을 사용하면 null 체크를 간소화하고, null이 발생했을 때 예외를 방지할 수 있습니다.

Null 체크 메서드

  • Objects 클래스의 isNull()과 nonNull() 메서드를 사용하여 체크

Null 병합 연산자

  • ?? 연산자를 사용
  • null 이면 기본값을 반환

Question

Java에서 null을 안전하게 다루는 방법은 무엇인가요?

명시적으로 조건문을 사용해 확인하는 방법이 있고, java 8 이후부터 도입된 Optional 클래스를 이용하여 안전하게 처리할 수 있습니다. 또는 Objects의 isNull과 nonNull메서드를 사용하거나, @Nullable, @NonNull 어노테이션을 사용할 수도 있습니다.

7. JDK와 JRE의 차이점

JDK(Java Development Kit)

  • JDK는 Java 애플리케이션을 개발할 수 있도록 필요한 모든 도구와 라이브러리를 포함한 개발 키트
  • JRE, Java 컴파일러, 디버거, javadoc 등으로 구성
  • Java 프로그램을 개발하고 컴파일하며 디버깅하는데 사용

JRE(Java Runtime Enviorment)

  • Java 애플리케이션을 실행할 수 있는 환경을 제공하는 소프트웨어
  • JVM, Java 표준 라이브러리로 구성
  • Java 프로그램을 실행하는 데 필요한 환경 제공
  • Java 개발을 위한 도구는 포함하지 않고, 단지 실행만을 위한 환경

Question

JDK와 JRE의 차이점에 대해 설명해주세요.

JDK는 Java 애플리케이션을 개발하기 위한 도구 모음이며, JRE는 Java 프로그램을 실행하기 위해 환경을 제공하는 소프트웨어입니다.


Question

JVM과 JRE, JDK의 관계를 계층적으로 설명하고, JDK 없이 JRE만으로 애플리케이션을 배포하는 상황에서 발생할 수 있는 문제점에 대해 논의해보세요.

JVM은 자바 애플리케이션 실행을 담당하는 핵심 엔진입니다. JVM은 자바 바이트코드를 해석하거나 JIT 컴파일러를 통해 기계어로 변환해 실행합니다. JRE는 JVM과 실행에 필요한 클래스 라이브러리 및 구성 요소를 포함하여 실행 환경을 제공합니다. JDK는 JRE에 개발 도구(컴파일러, 디버거 등)를 추가한 패키지입니다.

컴파일 이슈: JRE만 있을 경우, 개발자는 소스코드를 바이트코드로 변환(javac)할 수 없습니다. 배포 전 소스코드 수정이 필요한 상황에서 JDK가 없으면 애플리케이션을 수정하거나 빌드할 수 없습니다. 디버깅 제한: JRE만 있으면 런타임 중 문제를 파악하거나 디버깅 도구를 사용할 수 없어 문제 해결이 어렵습니다. 자동화 문제: CI/CD와 같은 빌드 자동화 환경에서는 JDK가 필요합니다. 빌드와 실행 환경이 분리되지 않으면 배포 중 문제가 발생할 가능성이 높습니다.

Question

대규모 트래픽을 처리하는 자바 백엔드 시스템에서 강한 결합과 느슨한 결합은 각각 어디에서 사용하면 적합할까요? 구체적인 사례를 들어 설명해주세요.

대규모 트래픽을 처리하는 시스템의 서비스 계층이나 비즈니스 로직 계층에서는 느슨한 결합을 활용하여 변경에 유연하게 대처합니다. 예를 들어, 결제 서비스에서 다양한 결제 게이트웨이를 처리하기 위해 PaymentGateway 인터페이스를 설계하고, 각각의 게이트웨이를 독립적으로 구현합니다.

강한 결합: 반대로, 시스템의 성능과 안정성이 중요한 캐싱 로직이나 데이터베이스 트랜잭션 관리에서는 강한 결합을 사용하여 불필요한 추상화를 줄이고 성능을 최적화할 수 있습니다. 예를 들어, Redis 캐싱 로직에서 클라이언트 객체를 직접 생성하고 사용합니다.

Question

자바 직렬화의 기본 구현이 가지는 단점은 무엇이고, 이를 해결하기 위한 대안 기술에는 무엇이 있나요?

성능 문제: 기본 직렬화는 자바 객체를 바이트 스트림으로 변환하는 데 비용이 많이 듭니다. 보안 문제: 역직렬화 과정에서 악의적인 데이터를 통해 java.io.ObjectInputStream이 보안 취약점을 노출할 수 있습니다. 호환성 문제: 클래스 구조가 변경되었을 때, serialVersionUID가 맞지 않으면 직렬화된 객체를 복원할 수 없습니다. 읽기 어려움: 기본 직렬화 형식은 사람이 읽을 수 없고, 특정 목적(예: 데이터 교환)에 적합하지 않습니다.

대안 기술: JSON 또는 XML: Jackson, Gson과 같은 라이브러리를 활용해 데이터를 구조화된 텍스트 형식으로 변환. Protocol Buffers, Avro, Thrift: 고성능 이진 직렬화 형식으로, 크기가 작고 더 빠릅니다. Kryo: 자바의 대체 직렬화 라이브러리로, 속도와 크기 면에서 효율적입니다.